今天延續昨天份的學習
在迴圈裡宣告的變數,算不算 re-declare ?
先公佈答案:不算。
var keepGoing = true;
while(keepGoing) {
let value = Math.random();
if (value > 0.5) {
keepGoing = false;
}
}
value
被 re-declare 了嗎? 沒有。
為什麼?
每跑一次迴圈,就是產生宣告新的 value
變數,所以第一次與第二次 per scope instance 不會一樣,因此不是 "re-declare" 。
假如將 let
換成 const
也不會有 Error,因為每跑一次迴圈,就會產生獨一無二的 per scope instance,不是 "re-declare"。
還有,let, const
變數本身就不能做 re-declare 了,如果上面的 snippet 是 re-declare 的話,會跳 Syntax Error 才對。
var keepGoing = true;
while (keepGoing) {
var value = Math.random();
if (value > 0.5) {
keepGoing = false;
}
}
value
被 re-declare 了嗎? 沒有。
為什麼? var
變數不是可以 re-declare 嗎?
回想 var
變數的作用域,是 functional scope,不是 block scope。
因此第三行的 value
宣告,會被提升到 while()
的外層( globle scope ),與 keepGoing 在同個 scope。而迴圈裡的 var value = Math.random()
可以想成 value = Math.random()
,只是在做 re-assignment 而已。
for (let i = 0; i < 3; i++) {
let value = i * 10;
console.log(`${ i }: ${ value }`);
}
// 0: 0
// 1: 10
// 2: 20
let i = 0
看起來每跑一次迴圈,就會重新宣告一次對吧?
那麼 i
真的 re-declare 了嗎? 沒有。
為什麼?
真正發生的情況是這樣的:
{
// a fictional variable for illustration
let $$i = 0;
for ( /* nothing */; $$i < 3; $$i++) {
// here's our actual loop `i`!
let i = $$i;
let value = i * 10;
console.log(`${ i }: ${ value }`);
}
// 0: 0
// 1: 10
// 2: 20
}
i
變數的 scope 是在 for(...){} 裡面,不是外面。
每跑一次迴圈,會產生新的 i
和 value
per scope instance,所以不會 "re-declare"。
for (const i = 0; i < 3; i++) {
// oops, this is going to fail with
// a Type Error after the first iteration
}
是 Type Error
,但是在哪發生的 ... ?
我們將上面的 snippet 拆解其作用域
{
const $$i = 0;
for ( ; $$i < 3; $$i++) {
const i = $$i;
}
}
找到了嗎?在 incrementExpresstion $$i++
$$i 被 re-assignment 了。
所以通常在 for() 迴圈,initialExpression 會使用 var 或者 let 來宣告變數。
今天份的學習到這邊